home *** CD-ROM | disk | FTP | other *** search
/ System Booster / System Booster.iso / Texteditors / XDME / Src / cmd.c < prev    next >
C/C++ Source or Header  |  1996-09-26  |  36KB  |  1,850 lines

  1. /******************************************************************************
  2.  
  3.     MODUL
  4.     cmd.c
  5.  
  6.     DESCRIPTION
  7.     In this file you find all routines for programming like
  8.     IF, WHILE, REPEAT
  9.  
  10.     NOTES
  11.  
  12.     BUGS
  13.  
  14.     TODO
  15.  
  16.     EXAMPLES
  17.  
  18.     SEE ALSO
  19.  
  20.     INDEX
  21.  
  22.     HISTORY
  23.     14. Nov 1992    ada created
  24.  
  25. ******************************************************************************/
  26.  
  27. /**************************************
  28.         Includes
  29. **************************************/
  30. #include "defs.h"
  31. #define MYDEBUG     0
  32. #include "debug.h"
  33.  
  34.  
  35. /**************************************
  36.         Globale Variable
  37. **************************************/
  38. Prototype void do_if        (void);
  39. Prototype void do_repeat    (void);
  40. Prototype int  do_toggle    (int);
  41. Prototype void do_scanf     (void);
  42. Prototype void do_push        (void);
  43. Prototype void do_pop        (void);
  44. Prototype void do_swap        (void);
  45. Prototype void check_stack  (ED *);
  46.  
  47.  
  48. /**************************************
  49.       Interne Defines & Strukturen
  50. **************************************/
  51. typedef enum
  52. {
  53.     _IT_POS,
  54.     _IT_MODIFIED,
  55.     _IT_ICONMODE,
  56.     _IT_TABSTOP,
  57.     _IT_MARGIN,
  58.     _IT_INSERTMODE,
  59.     _IT_IGNORECASE,
  60.     _IT_WORDWRAP,
  61.     _IT_WWCOL,
  62.     _IT_WINDOW,
  63.     _IT_ICON,
  64.     _IT_PENS,
  65.     _IT_BLOCK,
  66.     _IT_AUTO,
  67.     _IT_SAVETABS,
  68.     _IT_ED,
  69.     _IT_DISCARD,
  70. } ItemType;
  71.  
  72. struct Item
  73. {
  74.     ItemType type;        /* _IT_xxx */
  75.     UWORD    size;        /* 1-normal, 2-special, 3-malloc'd */
  76.     ULONG    value;        /* value */
  77. };
  78.  
  79.  
  80. /**************************************
  81.         Interne Variable
  82. **************************************/
  83. static ULONG         MAX_STACK_SIZE = 0;
  84. static struct Item * ItemStack        = NULL;
  85. static UWORD         ItemStackDepth = 0;
  86.  
  87.  
  88. /**************************************
  89.        Interne Prototypes
  90. **************************************/
  91. static ItemType identify_item (char *);
  92.  
  93.  
  94. /*
  95.    IF condition trueaction, IFELSE condition trueaction falseaction
  96.  
  97.     condition:    !condition  NOT the specified condition.
  98.         #        toggle number is SET
  99.         top        top of file (on first line)
  100.         bot        end of file (on last line)
  101.         left        start of line (leftmost column)
  102.         right        end of line (nothing but spaces under and to the right)
  103.         modified    text has been modified
  104.         insert        currently in insert mode
  105.         y[<=>]#     cursor is (any OR combo of <,>,=) row #  (line numbers start at 1)
  106.         x[<=>]#     cursor is (<,>,<=,>=,<>) column #        (columns start at 1)
  107.                 <> means 'not equal'
  108.  
  109.         cl        char under cursor is lower case
  110.         cu        char under cursor is upper case
  111.         ca        char under cursor is alpha
  112.         cn        char under cursor is numeric
  113.         cb        char within selected block
  114.         c[<=>]#     char under cursor is (combo of <,>,and =) #,
  115.                 where # can be a
  116.  
  117.                 ASCII-code (numeric: hex, oct, dez)
  118.                 String (enclosed in ""). The cursor must
  119.                     be on the first letter of "string".
  120.                 Character-Group: [], i.e. c=[1-9] will be true
  121.                     if cursor is on any number. c=[a-zA-DF-H]
  122.                     is a valid construct !
  123.  
  124.         block        will BLOCK fail ?
  125.         selnext     will SELECT NEXT succeed ?
  126.         selprev     will SELECT PREV succeed ?
  127.  
  128.  and especially for WHILE
  129.  
  130.         true       infinite-loop (!)
  131.  
  132. */
  133.  
  134.  
  135. void do_if (void)
  136. {
  137.     BOOL    haselse = (av[0][2] == 'e'),    /* is there an ELSE ? */
  138.         iswhile = (av[0][0] == 'w'),    /* is this a WHILE ? */
  139.         istrue,                /* result of condition */
  140.         notop   = 0;            /* NOT ? */
  141.     BOOL    c,
  142.         cx,
  143.         cc;
  144.     UBYTE * buf1,                /* two buffers */
  145.       * buf2,
  146.       * ptr,                /* tmp ptr */
  147.       * cmpptr = NULL;
  148.     ED      * ep = Ep;
  149.     int     i,
  150.         j, /* PATCH_NULL */
  151.         n, /* PATCH_NULL */
  152.         /* cxn, unused var */
  153.         cn;
  154.  
  155.     buf1 = (UBYTE *)malloc(MAXLINELEN);     /* get two buffers */
  156.     buf2 = (UBYTE *)malloc(MAXLINELEN);
  157.  
  158.     if (buf1 == NULL || buf2 == NULL)
  159.     {
  160.     if (buf1) free(buf1);               /* :-( */
  161.     if (buf2) free(buf2);
  162.  
  163.     title ("No Memory!");
  164.     nomemory ();
  165.     return;
  166.     }
  167.  
  168.     /* prepare for Ctrl-C checking */
  169.  
  170.     breakreset ();
  171.  
  172.     ptr = av[1];
  173.  
  174.     /* check for NOT */
  175.  
  176.     if (*ptr == '!')
  177.     {
  178.     notop = 1;
  179.     ++ptr;
  180.     }
  181.  
  182.     c    = tolower(ptr[0]);
  183.     cn    = atoi ((char *)ptr);
  184.     cx    = tolower(ptr[1]);
  185.     /* cxn = atoi ((char *)ptr+1); dead assign */
  186.  
  187.     strcpy ((char *)buf1, (char *)av[2]);
  188.  
  189. loop:
  190.     istrue = 0;
  191.     i       = 0;
  192.     j       = 1; /* PATCH_NULL */
  193.  
  194.     switch (c)
  195.     {
  196.     case '$':
  197.     case '&':
  198.         {
  199.         char   ci;
  200.         char * str;
  201.  
  202.         for (j = 1; isalnum(ptr[j]); ++j);
  203.         ci = ptr[j];
  204.         ptr[j] = 0;
  205.         str = getvar(ptr+1);
  206.         ptr[j] = ci;
  207.         /* i = 0; dead assign */
  208.         if (str)
  209.         {
  210. #if 0
  211.             if (!is_number(str))
  212.             {
  213.             error ("%s:\nvariable %s does not contain an integer!\n(%s)",av[1], ptr+1, str);
  214.             goto done;
  215.             } /* if */
  216.             i = atoi(str);
  217.             free(str);
  218. #else
  219.             if (ci) {
  220.             if (is_number(str)) {
  221.                 i = atoi(str);
  222.             } else {
  223.                 i = 0x80000000;
  224.             } /* if */
  225.             strcpy (tmp_buffer, str);
  226.             cmpptr = tmp_buffer;
  227.             free(str);
  228.             goto conditional;
  229.             } /* if */
  230. #endif
  231.         } else
  232.         {
  233.             error ("%s:\nunknown variable %s", av[0], ptr+1);
  234.             goto done;
  235.         }
  236.         if (ci)
  237.             goto conditional;
  238.         istrue = (i != 0);
  239.         break;
  240.         }
  241.     case 'x':
  242.         if (!i)
  243.         i = ep->column + 1;
  244.  
  245.     case 'y':
  246.         if (!i)
  247.         i = ep->line + 1;
  248.  
  249. conditional:
  250.         {
  251.         /* int j, n; */
  252.         char any = 0;
  253.  
  254.         for (; ptr[j] != '<' && ptr[j] != '>' && ptr[j] != '=' && ptr[j]; ++j); /* j=1 deleted */
  255.         if (!ptr[j])
  256.         {
  257.             error ("%s:\nBad conditional:\n`%s'", av[0], av[1]);
  258.             goto done;
  259.         }
  260.  
  261.         for ( ; (ptr[j] == '<' || ptr[j] == '>' || ptr[j] == '=') && ptr[j]; ++j)
  262.         {
  263.             switch(ptr[j])
  264.             {
  265.             case '<':
  266.                 any |= 1;
  267.                 break;
  268.             case '=':
  269.                 any |= 2;
  270.                 break;
  271.             case '>':
  272.                 any |= 4;
  273.                 break;
  274.             }
  275.         }
  276.  
  277.         if (!ptr[j] || !any || any == 7)
  278.         {
  279.             error ("%s:\nBad conditional `%s':\nUnexp. EOL or wrong compare", av[0], av[1]);
  280.             goto done;
  281.         }
  282.  
  283.         for ( ; isspace (ptr[j]); ++j);
  284.         if (!ptr[j])
  285.         {
  286.             error ("%s:\nBad conditional `%s':\nUnexp. EOL", av[0], av[1]);
  287.             goto done;
  288.         }
  289.  
  290.  
  291.         if (ptr[j] == '"')
  292.         {
  293.             j ++;
  294.             for (n=j; ptr[j] != '"' && ptr[j]; j ++);
  295.             j -= n;
  296.  
  297.             if (ep->config.ignorecase)
  298.             n = strnicmp (cmpptr? cmpptr: (Current+ep->column), &ptr[n], j);
  299.             else
  300.             n = strncmp  (cmpptr? cmpptr: (Current+ep->column), &ptr[n], j);
  301.         } else if (ptr[j] == '[')
  302.         {
  303.             if (any != 2 && any != 5)
  304.             {
  305.             error ("%s:\nBad conditional `%s':\ncompare with [] must be '=' or '<>'", av[0], av[1]);
  306.             goto done;
  307.             }
  308.  
  309.             j ++;
  310.             cc = cmpptr? *cmpptr: Current[ep->column];
  311.  
  312.             for (/* n=j dead assign */; ptr[j] != ']' && ptr[j]; j ++)
  313.             {
  314.             if (ptr[j] == '\\') j ++;
  315.             else if (ptr[j+1] == '-')
  316.             {
  317.                 if (!ptr[j+2] || ptr[j+2] == ']')
  318.                 {
  319.                 error ("%s:\nBad conditional `%s':\nString ended too early", av[0], av[1]);
  320.                 goto done;
  321.                 }
  322.  
  323.                 if (cc >= ptr[j] && cc <= ptr[j+2])
  324.                 {
  325.                 cc = ptr[j];
  326.                 break;
  327.                 }
  328.  
  329.                 j += 3;
  330.                 continue;
  331.             }
  332.  
  333.             if (cc == ptr[j]) break;
  334.             }
  335.  
  336.             istrue = (cc==ptr[j] && any==2) || (cc!=ptr[j] && any==5);
  337.  
  338.             break;
  339.         } else if (isdigit(ptr[j]) || ptr[j] == '+' || ptr[j] == '-')
  340.         {
  341.             n = i - atoi((char *)ptr+j);
  342.         } else
  343.         {
  344.             error ("%s:\nUnknown conditional `%s'", av[0], av[1]);
  345.             goto done;
  346.         }
  347.  
  348.         istrue = (any&1 && n<0) || (any&2 && !n) || (any&4 && n>0);
  349.         }
  350.     break;
  351.  
  352.     case 't':
  353.         if (cx == 'r')
  354.         istrue = 1;
  355.         else
  356.         istrue = !ep->line;
  357.     break;
  358.  
  359.     case 'b':
  360.         if (cx == 'l')
  361.         istrue = block_ok ();
  362.         else istrue = ep->line == ep->lines-1;
  363.     break;
  364.  
  365.     case 'l':
  366.         istrue = !ep->column;
  367.     break;
  368.  
  369.     case 'r': {
  370.         UBYTE * ptr;
  371.         int len;
  372.  
  373.         ptr = CONTENTS(Current);
  374.  
  375.         len = Clen-1;
  376.  
  377.         while (len >= 0 && ptr[len] == ' ')
  378.         len --;
  379.  
  380.         istrue = ep->column > len;
  381.     break; }
  382.  
  383.     case 'm':
  384.         text_sync ();
  385.         istrue = ep->modified;
  386.     break;
  387.  
  388.     case 'e':
  389.         istrue = globalflags.Comlinemode;
  390.     break;
  391.  
  392.     case 'i':
  393.         istrue = ep->config.insertmode;
  394.     break;
  395.  
  396.     case 'c':
  397.         cc = Current[ep->column];
  398.  
  399.         switch(cx)
  400.         {
  401.         case 'b':
  402.             istrue = is_inblock (ep->line, -1) == BP_INSIDE;
  403.         break;
  404.  
  405.         case 'l':
  406.             istrue = islower (cc);
  407.         break;
  408.  
  409.         case 'u':
  410.             istrue = isupper (cc);
  411.         break;
  412.  
  413.         case 'a':
  414.             istrue = isalnum (cc);
  415.         break;
  416.  
  417.         case 'n':
  418.             istrue = isdigit (cc);
  419.         break;
  420.  
  421.         default:        /* c[<=>]#  */
  422.             i = Current[ep->column];
  423.             goto conditional;
  424.         break;
  425.         }
  426.     break;
  427.  
  428.     case 's':       /* SELNEXT/SELPREV */
  429.         switch (tolower (ptr[3]))
  430.         {
  431.         case 'n':
  432.             if (GetSucc ((struct Node *)Ep))
  433.             istrue = 1;
  434.         break;
  435.  
  436.         case 'p':
  437.             if (GetPred ((struct Node *)Ep))
  438.             istrue = 1;
  439.         break;
  440.         }
  441.     break;
  442.  
  443.     case 'g':                       /* PATCH_NULL: */
  444.         if (is_number(ptr+1))
  445.         {
  446.         cn = atoi(ptr+1);
  447.         c  = '0';
  448.         } /* if */
  449.     /* fall-through */
  450.  
  451.     default:
  452.         if (isdigit (c))
  453.         istrue = do_toggle (cn);
  454.         else
  455.         {
  456.         error ("%s:\nBad condition\n`%s'", av[0], av[1]);
  457.         }
  458.  
  459.     break;
  460.     }
  461.  
  462.     istrue = notop ? !istrue : (istrue != 0);
  463.  
  464.     if (istrue)
  465.     {
  466.     strcpy((char *)buf2, (char *)buf1); /* could be executed multiple
  467.                            times */
  468.     if (do_command((char *)buf2) == 0)
  469.         goto done;
  470.  
  471.     if (iswhile && !globalflags.Abortcommand)
  472.     {
  473.  
  474.         if (breakcheck())
  475.         {
  476.         globalflags.Abortcommand = 1;
  477.         } else if (LoopCont)
  478.         {
  479.         LoopCont = 0;        /* PATCH_NULL [14 Feb 1993] : func <-> ass */
  480.         goto loop;
  481.         } else if (LoopBreak)
  482.         {
  483.         LoopBreak = 0;        /* PATCH_NULL [14 Feb 1993] : func <-> ass */
  484.         }
  485.         else
  486.         goto loop;
  487.     }
  488.     } else
  489.     {
  490.     if (haselse)
  491.     {       /* only executed once */
  492.         strcpy((char *)buf2, (char *)av[3]);
  493.         do_command((char *)buf2);
  494.     }
  495.     }
  496.  
  497. done:
  498.     free(buf1);
  499.     free(buf2);
  500. } /* do_if */
  501.  
  502.  
  503. /*
  504.  * repeat X command
  505.  *
  506.  * (if X is not a number it can be abbr. with 2 chars)
  507.  *
  508.  * X =    N     -number of repeats
  509.  *    line  -current line # (lines begin at 1)
  510.  *    lbot  -#lines to the bottom, inc. current
  511.  *    cleft -column # (columns begin at 0)
  512.  *        (thus is also chars to the left)
  513.  *    cright-#chars to eol, including current char
  514.  *    tr    -#char positions to get to next tab stop
  515.  *    tl    -#char positions to get to next backtab stop
  516.  */
  517.  
  518. #define SC(a,b) ((a)<<8|(b))
  519.  
  520. void do_repeat (void)
  521. {
  522.     UBYTE *ptr = av[1];
  523.     unsigned long n;
  524.     char *buf1, *buf2;
  525.  
  526.     if (!(buf1 = AllocMem (MAXLINELEN*2, 0)) )
  527.     {
  528.     globalflags.Abortcommand = 1;
  529.     return;
  530.     }
  531.  
  532.     buf2 = buf1 + MAXLINELEN;
  533.  
  534.     breakreset ();
  535.     strcpy (buf1, av[2]);
  536.  
  537.     switch (SC(ptr[0],ptr[1]))
  538.     {
  539.     case SC('l','i'):
  540.         n = text_lineno ();
  541.         break;
  542.  
  543.     case SC('l','b'):
  544.         n = text_lines () - text_lineno () + 1;
  545.         break;
  546.  
  547.     case SC('c','l'):
  548.         n = text_colno ();
  549.         break;
  550.  
  551.     case SC('c','r'):
  552.         n = text_cols () - text_colno ();
  553.         break;
  554.  
  555.     case SC('t','r'):
  556.         n = text_tabsize () - (text_colno () % text_tabsize ());
  557.         break;
  558.  
  559.     case SC('t','l'):
  560.         n = text_colno () % text_tabsize ();
  561.  
  562.         if (n == 0)
  563.         n = text_tabsize ();
  564.  
  565.         break;
  566.     default:
  567.         n = atoi (av[1]);
  568.         break;
  569.     }
  570.  
  571.     while (n > 0)
  572.     {
  573.     strcpy(buf2, buf1);
  574.  
  575.     if (do_command (buf2) == 0 || breakcheck ())
  576.     {
  577.         globalflags.Abortcommand = 1;
  578.         break;
  579.     }
  580.     if (LoopBreak)
  581.     {
  582.         LoopBreak = 0;        /* PATCH_NULL [14 Feb 1993] : func <-> ass */
  583.         break;
  584.     } else if (LoopCont)
  585.     {
  586.         LoopCont = 0;        /* PATCH_NULL [14 Feb 1993] : func <-> ass */
  587.     } /* if */
  588.  
  589.     --n;
  590.     }
  591.  
  592.     FreeMem (buf1, MAXLINELEN*2);
  593. } /* do_repeat */
  594.  
  595.  
  596. /*
  597.  * TOGGLE #, SETTOGGLE #, RESETTOGGLE #
  598.  */
  599.  
  600. UBYTE bit[] =
  601. {
  602.     0x01, 0x02, 0x04, 0x08,
  603.     0x10, 0x20, 0x40, 0x80
  604. };
  605.  
  606. int do_toggle (int n)
  607. {
  608.     extern UBYTE tg[MAXTOGGLE/8];
  609.     int i;
  610.  
  611.     if (n >= 0)
  612.     {
  613.     if (n >= MAXTOGGLE)
  614.         return(0);
  615.  
  616. /*printf ("Pos %d (%d/%d) %02x\n", n, n/8, n&7, tg[n/8]);*/
  617.  
  618.     return(tg[n/8] & bit[n&7]);
  619.     }
  620.  
  621.     i = atoi((char *)av[1]);
  622.  
  623.     n = i/8;
  624.     i &= 7;
  625.  
  626.     if (i >= 0 && i < MAXTOGGLE)
  627.     {
  628.     switch(av[0][0])
  629.     {
  630.         case 't':
  631.         tg[n] ^= bit[i];
  632.         break;
  633.         case 's':
  634.         tg[n] |= bit[i];
  635.         break;
  636.         case 'r':
  637.         tg[n] &= ~bit[i];
  638.         break;
  639.     }
  640.     }
  641.  
  642.     return (0);
  643. } /* do_toggle */
  644.  
  645.  
  646.  
  647. /*
  648.  *  SCANF controlstring
  649.  *
  650.  *  The C scanf routine.  Only one variable, a string, is allowed in the
  651.  *  control string.
  652.  *
  653.  *  Modified by A. Digulla to be more useful for a text-editor.
  654.  *
  655.  *   %s and %[] are still working
  656.  *
  657.  *   Additional :     (w)ord    (l)ine    (n)umber  (b)lock   (c)har
  658.  *             (t)ext    (a)lpha   (r)emark
  659.  *
  660.  *   w - get word
  661.  *   l - get line with EVERYTHING
  662.  *   b - get all that fits into isalphanum()
  663.  *   c - get single char
  664.  *   t - like line, but without preceding and trailing spaces
  665.  *   a - all that fits into isalpha()
  666.  *   r - get c-style comment
  667.  *
  668.  *   if you precede a '+' to any of these, SCANF will start at the beginning
  669.  *   to the left
  670.  */
  671.  
  672. void do_scanf (void)
  673. {
  674.     UBYTE buf[MAXLINELEN], *ptr, *bptr;
  675.     WORD  t;
  676.     BOOL  left;
  677.  
  678.     buf[0] = 0;
  679.     ptr = av[1];
  680.  
  681.     if (*ptr == '%')
  682.     {
  683.       ptr ++;
  684.       if (*ptr == 's' || *ptr == '[')
  685.       {
  686.            if (*ptr == 's')
  687.            {
  688.             ptr ++;
  689.             *ptr = 0;       /* Make sure there is nothing else */
  690.            } else
  691.            {
  692.             ptr ++;
  693.             if (*ptr == '~') *ptr = '^';
  694.  
  695.             while (*ptr != ']') ptr ++;
  696.             ptr ++;
  697.             *ptr = 0;       /* dito */
  698.            } /* if (*ptr == 's') */
  699.  
  700.            sscanf(Current+Ep->column,av[1],buf);
  701.       } else
  702.       {
  703.            *buf = 0;
  704.       } /* if (*ptr == 's' && *ptr == '[') */
  705.     } else
  706.     {
  707.       if (*ptr == '+')
  708.       {
  709.            left = TRUE;
  710.            ptr ++;
  711.       } else
  712.            left = FALSE;
  713.  
  714.       Clen = strlen ((char *)Current);
  715.  
  716.       switch (*ptr)
  717.       {
  718.            case ('w') :
  719.            {
  720.             t = Ep->column;
  721.  
  722.             if (t > Clen)
  723.             {
  724.              buf[0] = 0;
  725.              break;
  726.             }
  727.  
  728.             ptr = Current+t;
  729.  
  730.             if (left)
  731.             {
  732.              while (t && *ptr != ' ')
  733.              {
  734.                   ptr --;
  735.                   t --;
  736.              }
  737.             }
  738.  
  739.             while (*ptr == ' ' && t < Clen)
  740.             {
  741.              ptr ++;
  742.              t ++;
  743.             }
  744.  
  745.             if (t == Clen)
  746.             {
  747.              buf[0] = 0;
  748.              break;
  749.             }
  750.  
  751.             bptr = buf;
  752.  
  753.             while (*ptr != ' ' && *ptr)
  754.              *bptr++ = *ptr++;
  755.  
  756.             *bptr = 0;
  757.            break; } /* case ('w') */
  758.  
  759.            case ('l') :
  760.            {
  761.             if (left)
  762.             {
  763.              strncpy ((char *)buf, (char *)Current, Clen);
  764.              buf[Clen] = 0;
  765.             } else
  766.             {
  767.              strncpy ((char *)buf, (char *)Current+Ep->column,
  768.                  Clen-Ep->column);
  769.              buf[Clen - Ep->column] = 0;
  770.             }
  771.  
  772.            break; } /* case ('l') */
  773.  
  774.            case ('n') :
  775.            {
  776.             t = Ep->column;
  777.  
  778.             if (t > Clen)
  779.             {
  780.              buf[0] = 0;
  781.              break;
  782.             }
  783.  
  784.             ptr = Current+t;
  785.  
  786.             if (left)
  787.             {
  788.              while (t && isdigit(*ptr))
  789.              {
  790.                   ptr --;
  791.                   t --;
  792.              }
  793.  
  794.              if (t)
  795.              {
  796.                   ptr ++;
  797.                   t ++;
  798.              }
  799.             }
  800.  
  801.             while (*ptr == ' ' && t < Clen)
  802.             {
  803.              ptr ++;
  804.              t ++;
  805.             }
  806.  
  807.             if (t == Clen)
  808.             {
  809.              buf[0] = 0;
  810.              break;
  811.             }
  812.  
  813.             bptr = buf;
  814.  
  815.             while (isdigit(*ptr))
  816.              *bptr++ = *ptr++;
  817.  
  818.             *bptr = 0;
  819.  
  820.            break; } /* case ('n') */
  821.  
  822.            case ('b') :
  823.            {
  824.             t = Ep->column;
  825.  
  826.             if (t > Clen)
  827.             {
  828.              buf[0] = 0;
  829.              break;
  830.             }
  831.  
  832.             ptr = Current+t;
  833.  
  834.             if (left)
  835.             {
  836.              while (t && isalnum(*ptr))
  837.              {
  838.                   ptr --;
  839.                   t --;
  840.              }
  841.  
  842.              if (t)
  843.              {
  844.                   ptr ++;
  845.                   t ++;
  846.              }
  847.             }
  848.  
  849.             while (*ptr == ' ' && t < Clen)
  850.             {
  851.              ptr ++;
  852.              t ++;
  853.             }
  854.  
  855.             if (t == Clen)
  856.             {
  857.              buf[0] = 0;
  858.              break;
  859.             }
  860.  
  861.             bptr = buf;
  862.  
  863.             while (isalnum(*ptr))
  864.              *bptr++ = *ptr++;
  865.  
  866.             *bptr = 0;
  867.  
  868.            break; } /* case ('b') */
  869.  
  870.            case ('c') :
  871.            {
  872.             *buf = *(Current+Ep->column);
  873.             buf[1] = 0;
  874.  
  875.            break; } /* case ('c') */
  876.  
  877.            case ('t') :
  878.            {
  879.             if (left)
  880.             {
  881.              ptr = Current;
  882.              t = 0;
  883.             } else
  884.             {
  885.              t = Ep->column;
  886.              ptr = Current+t;
  887.             }
  888.  
  889.             if (t >= Clen || Clen == 0)
  890.             {
  891.              buf[0] = 0;
  892.              break;
  893.             }
  894.  
  895.             while (*ptr == ' ')
  896.             {
  897.              ptr ++;
  898.              t ++;
  899.             }
  900.  
  901.             if (t >= Clen)
  902.             {
  903.              buf[0] = 0;
  904.              break;
  905.             }
  906.  
  907.             strncpy ((char *)buf, (char *)ptr, Clen-t);
  908.  
  909.             ptr = buf + Clen - t - 1;
  910.  
  911.             while (*ptr == ' ')
  912.              ptr --;
  913.  
  914.             ptr[1] = 0;
  915.  
  916.            break; } /* case ('t') */
  917.  
  918.            case ('a') :
  919.            {
  920.             t = Ep->column;
  921.             ptr = Current+t;
  922.  
  923.             if (left)
  924.             {
  925.              while (isalpha(*ptr) && t)
  926.              {
  927.                   ptr --;
  928.                   t --;
  929.              }
  930.  
  931.              if (t)
  932.              {
  933.                   ptr ++;
  934.                   /* t ++; */
  935.              }
  936.             }
  937.  
  938.             bptr = buf;
  939.  
  940.             while (isalpha(*ptr))
  941.              *bptr++ = *ptr ++;
  942.  
  943.             *bptr = 0;
  944.  
  945.            break; } /* case ('a') */
  946.  
  947.            case ('r') :
  948.            {
  949.             t = Ep->column;
  950.             ptr = Current+t;
  951.  
  952.             if (left)
  953.             {
  954.              while (t)
  955.              {
  956.                   if (*ptr == '*' && *(ptr-1) == '/')
  957.                   {
  958.                    ptr ++;
  959.                    break;
  960.                   }
  961.  
  962.                   t --;
  963.                   ptr --;
  964.              }
  965.  
  966.              if (!t)
  967.              {
  968.                   *buf = 0;
  969.                   break;
  970.              } else
  971.              {
  972.                   t ++;
  973.                   ptr ++;
  974.              }
  975.             }
  976.  
  977.             if (t > Clen)
  978.             {
  979.              *buf = 0;
  980.              break;
  981.             }
  982.  
  983.             bptr = buf;
  984.  
  985.             while (t < Clen)
  986.             {
  987.              if (*ptr == '*' && ptr[1] == '/')
  988.              {
  989.                   bptr --;
  990.                   break;
  991.              }
  992.  
  993.              *bptr++ = *ptr ++;
  994.              t ++;
  995.             }
  996.  
  997.             *bptr = 0;
  998.  
  999.            break; } /* case ('r') */
  1000.  
  1001.       } /* switch (*ptr) */
  1002.     } /* if (*ptr == '%') */
  1003.  
  1004.     if (String)
  1005.     free (String);
  1006.  
  1007.     if (String = (char *)malloc (strlen ((char *)buf)+1))
  1008.     {
  1009.     strcpy ((char *)String, (char *)buf);
  1010.  
  1011.     title (String);
  1012.     }
  1013. } /* do_scanf */
  1014.  
  1015.  
  1016. /*****************************************************************************
  1017.  
  1018.     NAME
  1019.     do_push
  1020.  
  1021.     PARAMETER
  1022.     item
  1023.  
  1024.     DESCRIPTION
  1025.     Pushes an item on the internal stack.
  1026.  
  1027. ******************************************************************************/
  1028.  
  1029. void do_push (void)
  1030. {
  1031.     if (ItemStackDepth == MAX_STACK_SIZE)
  1032.     {
  1033.     struct Item * stack;
  1034.  
  1035.     if (stack = AllocMem (sizeof(struct Item) * (MAX_STACK_SIZE + 32), 0))
  1036.     {
  1037.         if (MAX_STACK_SIZE)
  1038.         movmem (ItemStack, stack, sizeof(struct Item)*MAX_STACK_SIZE);
  1039.  
  1040.         MAX_STACK_SIZE += 32;
  1041.         ItemStack = stack;
  1042.     } else
  1043.     {
  1044.         error ("push:\nCannot push %s:\nStack full", av[1]);
  1045.         return;
  1046.     }
  1047.     }
  1048.  
  1049.     switch (ItemStack[ItemStackDepth].type = identify_item (av[1]))
  1050.     {
  1051.     case _IT_POS:
  1052.     {
  1053.         struct TextMarker * pos;
  1054.  
  1055.         if (pos = malloc (sizeof(struct TextMarker)))
  1056.         {
  1057.         pos->ep     = Ep;
  1058.         pos->line   = Ep->line;
  1059.         pos->column = Ep->column;
  1060.  
  1061.         ItemStack[ItemStackDepth].value = (ULONG)pos;
  1062.         ItemStack[ItemStackDepth].size    = 3;
  1063.         } else
  1064.         {
  1065. out_of_memory:
  1066.         title ("push: Out of memory error");
  1067.         globalflags.Abortcommand = 1;
  1068.         return;
  1069.         }
  1070.     } break;
  1071.  
  1072.     case _IT_MODIFIED:
  1073.         ItemStack[ItemStackDepth].value = Ep->modified;
  1074.         ItemStack[ItemStackDepth].size  = 1;
  1075.     break;
  1076.  
  1077.     case _IT_ICONMODE:
  1078.         ItemStack[ItemStackDepth].value = Ep->iconmode;
  1079.         ItemStack[ItemStackDepth].size  = 1;
  1080.     break;
  1081.  
  1082.     case _IT_TABSTOP:
  1083.         ItemStack[ItemStackDepth].value = Ep->config.tabstop;
  1084.         ItemStack[ItemStackDepth].size  = 1;
  1085.     break;
  1086.  
  1087.     case _IT_MARGIN:
  1088.         ItemStack[ItemStackDepth].value = Ep->config.margin;
  1089.         ItemStack[ItemStackDepth].size  = 1;
  1090.     break;
  1091.  
  1092.     case _IT_INSERTMODE:
  1093.         ItemStack[ItemStackDepth].value = Ep->config.insertmode;
  1094.         ItemStack[ItemStackDepth].size  = 1;
  1095.     break;
  1096.  
  1097.     case _IT_IGNORECASE:
  1098.         ItemStack[ItemStackDepth].value = Ep->config.ignorecase;
  1099.         ItemStack[ItemStackDepth].size  = 1;
  1100.     break;
  1101.  
  1102.     case _IT_WORDWRAP:
  1103.         ItemStack[ItemStackDepth].value = Ep->config.wordwrap;
  1104.         ItemStack[ItemStackDepth].size  = 1;
  1105.     break;
  1106.  
  1107.     case _IT_WWCOL:
  1108.         ItemStack[ItemStackDepth].value = Ep->config.wwcol;
  1109.         ItemStack[ItemStackDepth].size  = 1;
  1110.     break;
  1111.  
  1112.     case _IT_SAVETABS:
  1113.         ItemStack[ItemStackDepth].value = globalflags.Savetabs;
  1114.         ItemStack[ItemStackDepth].size  = 1;
  1115.     break;
  1116.  
  1117.     case _IT_ED:
  1118.         ItemStack[ItemStackDepth].value = (ULONG)Ep;
  1119.         ItemStack[ItemStackDepth].size  = 2;
  1120.     break;
  1121.  
  1122.     case _IT_WINDOW:
  1123.     {
  1124.         UWORD * array;
  1125.  
  1126.         if (array = malloc (4*sizeof(UWORD)))
  1127.         {
  1128.         if (!Ep->iconmode)
  1129.         {
  1130.             array[0] = Ep->config.winx;
  1131.             array[1] = Ep->config.winy;
  1132.             array[2] = Ep->config.winwidth;
  1133.             array[3] = Ep->config.winheight;
  1134.         } else
  1135.         {
  1136.             array[0] = Ep->win->LeftEdge;
  1137.             array[1] = Ep->win->TopEdge;
  1138.             array[2] = Ep->win->Width;
  1139.             array[3] = Ep->win->Height;
  1140.         }
  1141.  
  1142.         ItemStack[ItemStackDepth].value = (ULONG)array;
  1143.         ItemStack[ItemStackDepth].size    = 3;
  1144.         } else
  1145.         {
  1146.         goto out_of_memory;
  1147.         }
  1148.     } break;
  1149.  
  1150.     case _IT_ICON:
  1151.     {
  1152.         UWORD * array;
  1153.  
  1154.         if (array = malloc (2*sizeof(UWORD)))
  1155.         {
  1156.         if (Ep->iconmode)
  1157.         {
  1158.             array[0] = Ep->config.iwinx;
  1159.             array[1] = Ep->config.iwiny;
  1160.         } else
  1161.         {
  1162.             array[0] = Ep->win->LeftEdge;
  1163.             array[1] = Ep->win->TopEdge;
  1164.         }
  1165.  
  1166.         ItemStack[ItemStackDepth].value = (ULONG)array;
  1167.         ItemStack[ItemStackDepth].size    = 3;
  1168.         } else
  1169.         {
  1170.         goto out_of_memory;
  1171.         }
  1172.     } break;
  1173.  
  1174.     case _IT_PENS:
  1175.     {
  1176.         ULONG * array;
  1177.  
  1178.         if (array = malloc (5*sizeof(ULONG)))
  1179.         {
  1180.         array[0] = TEXT_FPEN;
  1181.         array[1] = TEXT_BPEN;
  1182.         array[2] = BLOCK_FPEN;
  1183.         array[3] = BLOCK_BPEN;
  1184.         array[4] = TITLE_BPEN;
  1185.  
  1186.         ItemStack[ItemStackDepth].value = (ULONG)array;
  1187.         ItemStack[ItemStackDepth].size    = 3;
  1188.         } else
  1189.         {
  1190.         goto out_of_memory;
  1191.         }
  1192.     } break;
  1193.  
  1194.     case _IT_BLOCK:
  1195.     {
  1196.         Block * block;
  1197.  
  1198.         if (block = malloc (sizeof(Block)))
  1199.         {
  1200.         movmem (&ActualBlock, block, sizeof (Block));
  1201.  
  1202.         ItemStack[ItemStackDepth].value = (ULONG)block;
  1203.         ItemStack[ItemStackDepth].size    = 3;
  1204.  
  1205.         if (!Ep->iconmode)
  1206.             text_redrawblock (0);
  1207.         } else
  1208.         {
  1209.         goto out_of_memory;
  1210.         }
  1211.     } break;
  1212.  
  1213.     default:
  1214.         error ("push:\nUnknown item\n`%s'", av[1]);
  1215.         return;
  1216.     break;
  1217.     }
  1218.  
  1219.     ItemStackDepth ++;
  1220.  
  1221. #if MYDEBUG
  1222.     if (globalflags.debug)
  1223.     D(bug("PUSH Stack %d\n", ItemStackDepth));
  1224. #endif
  1225. } /* do_push */
  1226.  
  1227.  
  1228. /*****************************************************************************
  1229.  
  1230.     NAME
  1231.     POP/PEEK item
  1232.  
  1233.     PARAMETER
  1234.     item / AUTO / DISCARD
  1235.  
  1236.     DESCRIPTION
  1237.     Pops an item from the internal stack or (PEEK) just get's the value
  1238.     of it without poping it from the stack.
  1239.  
  1240. ******************************************************************************/
  1241.  
  1242. void do_pop (void)
  1243. {
  1244.     ItemType type;
  1245.  
  1246.     if (ItemStackDepth == 0)
  1247.     {
  1248.     error ("%s:\nCannot pop %s:\nStack empty", av[0], av[1]);
  1249.     return;
  1250.     }
  1251.  
  1252.     ItemStackDepth --;
  1253.  
  1254. #if MYDEBUG
  1255.     if (globalflags.debug)
  1256.     D(bug("%s Stack %d\n", av[0], ItemStackDepth));
  1257. #endif
  1258.  
  1259.     type = identify_item (av[1]);
  1260.  
  1261.     if (type == _IT_AUTO)
  1262.     type = ItemStack[ItemStackDepth].type;
  1263.  
  1264.     switch (type)
  1265.     {
  1266.     case _IT_POS: {
  1267.         struct TextMarker * pos;
  1268.  
  1269.         if (ItemStack[ItemStackDepth].type != _IT_POS)
  1270.         error ("%s:\nCannot pop position\nto something else", av[0]);
  1271.  
  1272.         pos = (struct TextMarker *)ItemStack[ItemStackDepth].value;
  1273.  
  1274.         text_sync ();
  1275.  
  1276.         text_cursor (1);
  1277.         switch_ed (pos->ep);
  1278.         text_cursor (0);
  1279.  
  1280.         if (IntuitionBase->ActiveWindow != Ep->win)
  1281.         {
  1282.         WindowToFront (Ep->win);
  1283.         ActivateWindow (Ep->win);
  1284.         }
  1285.  
  1286.         if (pos->line >= Ep->lines)
  1287.         Ep->line = Ep->lines - 1;
  1288.         else
  1289.         Ep->line = pos->line;
  1290.  
  1291.         Ep->column = pos->column;
  1292.  
  1293.         text_load ();
  1294.         text_adjust (FALSE);
  1295.     break; }
  1296.  
  1297.     case _IT_MODIFIED:
  1298.         if (ItemStack[ItemStackDepth].size != 1)
  1299.         error ("%s:\nCannot pop a struct\nto modified", av[0]);
  1300.  
  1301.         Ep->modified = ItemStack[ItemStackDepth].value;
  1302.     break;
  1303.  
  1304.     case _IT_ICONMODE:
  1305.         if (ItemStack[ItemStackDepth].size != 1)
  1306.         error ("%s:\nCannot pop a struct\nto iconmode", av[0]);
  1307.  
  1308.         if (Ep->iconmode != ItemStack[ItemStackDepth].value)
  1309.         {
  1310.         if (ItemStack[ItemStackDepth].value)
  1311.             iconify ();
  1312.         else
  1313.             uniconify ();
  1314.         }
  1315.     break;
  1316.  
  1317.     case _IT_TABSTOP:
  1318.         if (ItemStack[ItemStackDepth].size != 1)
  1319.         error ("%s:\nCannot pop a struct\nto tabstop", av[0]);
  1320.  
  1321.         Ep->config.tabstop = ItemStack[ItemStackDepth].value;
  1322.     break;
  1323.  
  1324.     case _IT_MARGIN:
  1325.         if (ItemStack[ItemStackDepth].size != 1)
  1326.         error ("%s:\nCannot pop a struct\nto margin", av[0]);
  1327.  
  1328.         Ep->config.margin = ItemStack[ItemStackDepth].value;
  1329.     break;
  1330.  
  1331.     case _IT_INSERTMODE:
  1332.         if (ItemStack[ItemStackDepth].size != 1)
  1333.         error ("%s:\nCannot pop a struct\nto insertmode", av[0]);
  1334.  
  1335.         Ep->config.insertmode = ItemStack[ItemStackDepth].value;
  1336.     break;
  1337.  
  1338.     case _IT_IGNORECASE:
  1339.         if (ItemStack[ItemStackDepth].size != 1)
  1340.         error ("%s:\nCannot pop a struct\nto ignorecase", av[0]);
  1341.  
  1342.         Ep->config.ignorecase = ItemStack[ItemStackDepth].value;
  1343.     break;
  1344.  
  1345.     case _IT_WORDWRAP:
  1346.         if (ItemStack[ItemStackDepth].size != 1)
  1347.         error ("%s:\nCannot pop a struct\nto wordwrap", av[0]);
  1348.  
  1349.         Ep->config.wordwrap = ItemStack[ItemStackDepth].value;
  1350.     break;
  1351.  
  1352.     case _IT_WWCOL:
  1353.         if (ItemStack[ItemStackDepth].size != 1)
  1354.         error ("%s:\nCannot pop a struct\nto wordwrapcolumn", av[0]);
  1355.  
  1356.         Ep->config.wwcol = ItemStack[ItemStackDepth].value;
  1357.     break;
  1358.  
  1359.     case _IT_SAVETABS:
  1360.         if (ItemStack[ItemStackDepth].size != 1)
  1361.         error ("%s:\nCannot pop a struct\nto savetabs", av[0]);
  1362.  
  1363.         globalflags.Savetabs = ItemStack[ItemStackDepth].value;
  1364.     break;
  1365.  
  1366.     case _IT_ED:
  1367.         if (ItemStack[ItemStackDepth].type != _IT_ED)
  1368.         error ("%s:\nCannot pop ed\nto something else", av[0]);
  1369.  
  1370.         switch_ed ((ED *)ItemStack[ItemStackDepth].value);
  1371.     break;
  1372.  
  1373.     case _IT_WINDOW: {
  1374.         UWORD * array;
  1375.  
  1376.         if (ItemStack[ItemStackDepth].type != _IT_WINDOW)
  1377.         error ("%s:\nCannot pop window\nto something else", av[0]);
  1378.  
  1379.         array = (UWORD *)ItemStack[ItemStackDepth].value;
  1380.  
  1381.         Ep->config.winx     = array[0];
  1382.         Ep->config.winy     = array[1];
  1383.         Ep->config.winwidth  = array[2];
  1384.         Ep->config.winheight = array[3];
  1385.  
  1386.         if (!Ep->iconmode)
  1387.         {
  1388.         MoveWindow (Ep->win, Ep->config.winx - Ep->win->LeftEdge,
  1389.                      Ep->config.winy - Ep->win->TopEdge);
  1390.         SizeWindow (Ep->win, Ep->config.winwidth  - Ep->win->Width,
  1391.                      Ep->config.winheight - Ep->win->Height);
  1392.         }
  1393.     break; }
  1394.  
  1395.     case _IT_ICON: {
  1396.         UWORD * array;
  1397.  
  1398.         if (ItemStack[ItemStackDepth].type != _IT_ICON)
  1399.         error ("%s:\nCannot pop icon\nto something else", av[0]);
  1400.  
  1401.         array = (UWORD *)ItemStack[ItemStackDepth].value;
  1402.  
  1403.         Ep->config.iwinx      = array[0];
  1404.         Ep->config.iwiny      = array[1];
  1405.  
  1406.         if (Ep->iconmode)
  1407.         {
  1408.         MoveWindow (Ep->win, Ep->config.iwinx - Ep->win->LeftEdge,
  1409.                      Ep->config.iwiny - Ep->win->TopEdge);
  1410.         }
  1411.     break; }
  1412.  
  1413.     case _IT_PENS: {
  1414.         ULONG * array;
  1415.  
  1416.         if (ItemStack[ItemStackDepth].type != _IT_PENS)
  1417.         error ("%s:\nCannot pop pens\nto something else", av[0]);
  1418.  
  1419.         array = (ULONG *)ItemStack[ItemStackDepth].value;
  1420.  
  1421.         TEXT_FPEN  = array[0];
  1422.         TEXT_BPEN  = array[1];
  1423.         BLOCK_FPEN = array[2];
  1424.         BLOCK_BPEN = array[3];
  1425.         TITLE_BPEN = array[4];
  1426.  
  1427.         if (!Ep->iconmode)
  1428.         text_redisplay ();
  1429.  
  1430.         globalflags.MForceTitle = 1;
  1431.     break; }
  1432.  
  1433.     case _IT_BLOCK: {
  1434.         Block * block;
  1435.  
  1436.         if (ItemStack[ItemStackDepth].type != _IT_BLOCK)
  1437.         error ("%s:\nCannot pop block\nto something else", av[0]);
  1438.  
  1439.         block = (Block *) ItemStack[ItemStackDepth].value;
  1440.  
  1441.         movmem (block, &ActualBlock, sizeof (Block));
  1442.  
  1443.         if (!Ep->iconmode)
  1444.         text_redrawblock (1);
  1445.     break; }
  1446.  
  1447.     case _IT_DISCARD:
  1448.     break;
  1449.  
  1450.     default:
  1451.         error ("%s:\nUnknown item\n`%s'", av[0], av[1]);
  1452.     break;
  1453.     }
  1454.  
  1455.     /* free only, if POP. If PEEK, restore Depth */
  1456.     if (av[0][1] == 'o' && av[0][2] == 'p')
  1457.     {
  1458.     if (ItemStack[ItemStackDepth].size == 3)
  1459.         free ((void *)ItemStack[ItemStackDepth].value);
  1460.     } else
  1461.     ItemStackDepth ++;
  1462. } /* do_pop */
  1463.  
  1464.  
  1465. /*****************************************************************************
  1466.  
  1467.     NAME
  1468.     SWAP item
  1469.  
  1470.     PARAMETER
  1471.     item / AUTO / DISCARD
  1472.  
  1473.     DESCRIPTION
  1474.     This exchanges the actual item with the item on stack, ie. the
  1475.     topmost item from stack is poped and the actual item is pushed.
  1476.  
  1477. ******************************************************************************/
  1478.  
  1479. void do_swap (void)
  1480. {
  1481.     ItemType type;
  1482.     ULONG    value;
  1483.  
  1484.     if (ItemStackDepth == 0)
  1485.     {
  1486.     error ("swap:\nCannot swap %s:\nStack empty", av[1]);
  1487.     return;
  1488.     }
  1489.  
  1490.     ItemStackDepth --;
  1491.  
  1492.     value = ItemStack[ItemStackDepth].value;
  1493.  
  1494. #if MYDEBUG
  1495.     if (globalflags.debug)
  1496.     D(bug("Stack %d\n", ItemStackDepth));
  1497. #endif
  1498.  
  1499.     type = identify_item (av[1]);
  1500.  
  1501.     if (type == _IT_AUTO)
  1502.     type = ItemStack[ItemStackDepth].type;
  1503.  
  1504.     switch (type)
  1505.     {
  1506.     case _IT_POS: {
  1507.         struct TextMarker pos;
  1508.  
  1509.         if (ItemStack[ItemStackDepth].type != _IT_POS)
  1510.         error ("%s:\nCannot swap position\nto something else", av[0]);
  1511.  
  1512.         pos.ep     = Ep;
  1513.         pos.line   = Ep->line;
  1514.         pos.column = Ep->column;
  1515.  
  1516.         swapmem ((void *)value, &pos, sizeof (struct TextMarker));
  1517.  
  1518.         text_sync ();
  1519.  
  1520.         text_cursor (1);
  1521.         switch_ed (pos.ep);
  1522.         text_cursor (0);
  1523.  
  1524.         if (IntuitionBase->ActiveWindow != Ep->win)
  1525.         {
  1526.         WindowToFront (Ep->win);
  1527.         ActivateWindow (Ep->win);
  1528.         }
  1529.  
  1530.         if (pos.line >= Ep->lines)
  1531.         Ep->line = Ep->lines - 1;
  1532.         else
  1533.         Ep->line = pos.line;
  1534.  
  1535.         Ep->column = pos.column;
  1536.  
  1537.         text_load ();
  1538.         text_adjust (FALSE);
  1539.     break; }
  1540.  
  1541.     case _IT_MODIFIED:
  1542.         if (ItemStack[ItemStackDepth].size != 1)
  1543.         error ("%s:\nCannot swap a struct\nto modified", av[0]);
  1544.  
  1545.         ItemStack[ItemStackDepth].value = Ep->modified;
  1546.         Ep->modified = value;
  1547.     break;
  1548.  
  1549.     case _IT_ICONMODE:
  1550.         if (ItemStack[ItemStackDepth].size != 1)
  1551.         error ("%s:\nCannot pop a struct\nto iconmode", av[0]);
  1552.  
  1553.         if (Ep->iconmode != ItemStack[ItemStackDepth].value)
  1554.         {
  1555.         if (ItemStack[ItemStackDepth].value)
  1556.             iconify ();
  1557.         else
  1558.             uniconify ();
  1559.         }
  1560.     break;
  1561.  
  1562.     case _IT_TABSTOP:
  1563.         if (ItemStack[ItemStackDepth].size != 1)
  1564.         error ("%s:\nCannot swap a struct\nto tabstop", av[0]);
  1565.  
  1566.         ItemStack[ItemStackDepth].value = Ep->config.tabstop;
  1567.         Ep->config.tabstop = value;
  1568.     break;
  1569.  
  1570.     case _IT_MARGIN:
  1571.         if (ItemStack[ItemStackDepth].size != 1)
  1572.         error ("%s:\nCannot swap a struct\nto margin", av[0]);
  1573.  
  1574.         ItemStack[ItemStackDepth].value = Ep->config.margin;
  1575.         Ep->config.margin = value;
  1576.     break;
  1577.  
  1578.     case _IT_INSERTMODE:
  1579.         if (ItemStack[ItemStackDepth].size != 1)
  1580.         error ("%s:\nCannot swap a struct\nto insertmode", av[0]);
  1581.  
  1582.         ItemStack[ItemStackDepth].value = Ep->config.insertmode;
  1583.         Ep->config.insertmode = value;
  1584.     break;
  1585.  
  1586.     case _IT_IGNORECASE:
  1587.         if (ItemStack[ItemStackDepth].size != 1)
  1588.         error ("%s:\nCannot swap a struct\nto ignorecase", av[0]);
  1589.  
  1590.         ItemStack[ItemStackDepth].value = Ep->config.ignorecase;
  1591.         Ep->config.ignorecase = value;
  1592.     break;
  1593.  
  1594.     case _IT_WORDWRAP:
  1595.         if (ItemStack[ItemStackDepth].size != 1)
  1596.         error ("%s:\nCannot swap a struct\nto wordwrap", av[0]);
  1597.  
  1598.         ItemStack[ItemStackDepth].value = Ep->config.wordwrap;
  1599.         Ep->config.wordwrap = value;
  1600.     break;
  1601.  
  1602.     case _IT_WWCOL:
  1603.         if (ItemStack[ItemStackDepth].size != 1)
  1604.         error ("%s:\nCannot swap a struct\nto wordwrapcolumn", av[0]);
  1605.  
  1606.         ItemStack[ItemStackDepth].value = Ep->config.wwcol;
  1607.         Ep->config.wwcol = value;
  1608.     break;
  1609.  
  1610.     case _IT_SAVETABS:
  1611.         if (ItemStack[ItemStackDepth].size != 1)
  1612.         error ("%s:\nCannot swap a struct\nto savetabs", av[0]);
  1613.  
  1614.         ItemStack[ItemStackDepth].value = globalflags.Savetabs;
  1615.         globalflags.Savetabs = value;
  1616.     break;
  1617.  
  1618.     case _IT_ED:
  1619.         if (ItemStack[ItemStackDepth].type != _IT_ED)
  1620.         error ("%s:\nCannot swap ed\nto something else", av[0]);
  1621.  
  1622.         ItemStack[ItemStackDepth].value = (ULONG)Ep;
  1623.         switch_ed ((ED *)value);
  1624.     break;
  1625.  
  1626.     case _IT_WINDOW: {
  1627.         UWORD array[4];
  1628.  
  1629.         if (ItemStack[ItemStackDepth].type != _IT_WINDOW)
  1630.         error ("%s:\nCannot swap window\nto something else", av[0]);
  1631.  
  1632.         if (!Ep->iconmode)
  1633.         {
  1634.         array[0] = Ep->config.winx;
  1635.         array[1] = Ep->config.winy;
  1636.         array[2] = Ep->config.winwidth;
  1637.         array[3] = Ep->config.winheight;
  1638.         } else
  1639.         {
  1640.         array[0] = Ep->win->LeftEdge;
  1641.         array[1] = Ep->win->TopEdge;
  1642.         array[2] = Ep->win->Width;
  1643.         array[3] = Ep->win->Height;
  1644.         }
  1645.  
  1646.         swapmem ((void *)value, array, sizeof(UWORD)*4);
  1647.  
  1648.         Ep->config.winx     = array[0];
  1649.         Ep->config.winy     = array[1];
  1650.         Ep->config.winwidth  = array[2];
  1651.         Ep->config.winheight = array[3];
  1652.  
  1653.         if (!Ep->iconmode)
  1654.         {
  1655.         MoveWindow (Ep->win, Ep->config.winx - Ep->win->LeftEdge,
  1656.                      Ep->config.winy - Ep->win->TopEdge);
  1657.         SizeWindow (Ep->win, Ep->config.winwidth  - Ep->win->Width,
  1658.                      Ep->config.winheight - Ep->win->Height);
  1659.         }
  1660.     break; }
  1661.  
  1662.     case _IT_ICON: {
  1663.         UWORD array[2];
  1664.  
  1665.         if (ItemStack[ItemStackDepth].type != _IT_ICON)
  1666.         error ("%s:\nCannot swap icon\nto something else", av[0]);
  1667.  
  1668.         if (Ep->iconmode)
  1669.         {
  1670.         array[0] = Ep->config.iwinx;
  1671.         array[1] = Ep->config.iwiny;
  1672.         } else
  1673.         {
  1674.         array[0] = Ep->win->LeftEdge;
  1675.         array[1] = Ep->win->TopEdge;
  1676.         }
  1677.  
  1678.         swapmem ((void *)value, array, sizeof(UWORD)*2);
  1679.  
  1680.         Ep->config.iwinx      = array[0];
  1681.         Ep->config.iwiny      = array[1];
  1682.  
  1683.         if (Ep->iconmode)
  1684.         {
  1685.         MoveWindow (Ep->win, Ep->config.iwinx - Ep->win->LeftEdge,
  1686.                      Ep->config.iwiny - Ep->win->TopEdge);
  1687.         }
  1688.     break; }
  1689.  
  1690.     case _IT_PENS: {
  1691.         ULONG array[5];
  1692.  
  1693.         if (ItemStack[ItemStackDepth].type != _IT_PENS)
  1694.         error ("%s:\nCannot swap pens\nto something else", av[0]);
  1695.  
  1696.         array[0] = TEXT_FPEN;
  1697.         array[1] = TEXT_BPEN;
  1698.         array[2] = BLOCK_FPEN;
  1699.         array[3] = BLOCK_BPEN;
  1700.         array[4] = TITLE_BPEN;
  1701.  
  1702.         swapmem ((void *)value, array, sizeof(ULONG)*5);
  1703.  
  1704.         TEXT_FPEN  = array[0];
  1705.         TEXT_BPEN  = array[1];
  1706.         BLOCK_FPEN = array[2];
  1707.         BLOCK_BPEN = array[3];
  1708.         TITLE_BPEN = array[4];
  1709.  
  1710.         if (!Ep->iconmode)
  1711.         text_redisplay ();
  1712.  
  1713.         globalflags.MForceTitle = 1;
  1714.     break; }
  1715.  
  1716.     case _IT_BLOCK: {
  1717.         Block block;
  1718.  
  1719.         if (ItemStack[ItemStackDepth].type != _IT_BLOCK)
  1720.         error ("%s:\nCannot swap block\nto something else", av[0]);
  1721.  
  1722.         movmem (&ActualBlock, &block, sizeof (Block));
  1723.  
  1724.         if (!Ep->iconmode)
  1725.         text_redrawblock (0);
  1726.  
  1727.         swapmem ((void *)value, &block, sizeof (Block));
  1728.  
  1729.         movmem (&block, &ActualBlock, sizeof (Block));
  1730.  
  1731.         if (!Ep->iconmode)
  1732.         text_redrawblock (1);
  1733.     break; }
  1734.  
  1735.     default:
  1736.         error ("swap:\nUnknown item\n`%s'", av[1]);
  1737.     break;
  1738.     }
  1739.  
  1740.     ItemStackDepth ++;
  1741. } /* do_swap */
  1742.  
  1743.  
  1744. static ItemType identify_item (char * itemname)
  1745. {
  1746.     static CONST struct
  1747.     {
  1748.     char   * name;
  1749.     ItemType type;
  1750.     } items[] =
  1751.     {
  1752.     "auto",         _IT_AUTO,
  1753.     "block",        _IT_BLOCK,
  1754.     "discard",      _IT_DISCARD,
  1755.     "ed",           _IT_ED,
  1756.     "icon",         _IT_ICON,
  1757.     "iconmode",     _IT_ICONMODE,
  1758.     "ignorecase",   _IT_IGNORECASE,
  1759.     "insertmode",   _IT_INSERTMODE,
  1760.     "margin",       _IT_MARGIN,
  1761.     "modified",     _IT_MODIFIED,
  1762.     "pens",         _IT_PENS,
  1763.     "pos",          _IT_POS,
  1764.     "savetabs",     _IT_SAVETABS,
  1765.     "tabstop",      _IT_TABSTOP,
  1766.     "window",       _IT_WINDOW,
  1767.     "wordwrap",     _IT_WORDWRAP,
  1768.     "wwcol",        _IT_WWCOL,
  1769.     };
  1770.     WORD  low,
  1771.       high,
  1772.       t,
  1773.       diff;
  1774.  
  1775.     low = 0;
  1776.     high = sizeof (items) / sizeof (items[0]) -1;
  1777.  
  1778.     do
  1779.     {
  1780.     t = (low + high) / 2;
  1781.  
  1782.     if (!(diff = stricmp (itemname, items[t].name)) )
  1783.         break;
  1784.     else if (diff < 0)
  1785.         high = t-1;
  1786.     else
  1787.         low = t+1;
  1788.     } while (low <= high);
  1789.  
  1790.     if (!diff)
  1791.     return (items[t].type);
  1792.  
  1793.     return (-1);
  1794. } /* identify_item */
  1795.  
  1796.  
  1797. /*****************************************************************************
  1798.  
  1799.     NAME
  1800.     check_stack
  1801.  
  1802.     PARAMETER
  1803.     ED * ep;
  1804.  
  1805.     DESCRIPTION
  1806.     Checks the stack for thing left from editor ep or if ep == NULL
  1807.     cleans the full stack.
  1808.  
  1809. ******************************************************************************/
  1810.  
  1811. void check_stack (ED * ep)
  1812. {
  1813.     WORD i, j;
  1814.  
  1815.     if (ep)
  1816.     {
  1817.     for (i=j=0; i<ItemStackDepth; i ++)
  1818.     {
  1819.         if (!((ItemStack[i].type == _IT_ED ||
  1820.             ItemStack[i].type == _IT_POS ||
  1821.             ItemStack[i].type == _IT_BLOCK) &&
  1822.             ep == *(ED **)ItemStack[i].value) )
  1823.             {
  1824.         if (i != j)
  1825.         {
  1826.             ItemStack[j] = ItemStack[i];
  1827.         }
  1828.  
  1829.         j ++;
  1830.         }
  1831.     }
  1832.  
  1833.     ItemStackDepth = j;
  1834.     } else
  1835.     {
  1836.     for (i=0; i<ItemStackDepth; i ++)
  1837.     {
  1838.         if (ItemStack[i].size == 3)
  1839.         free ((void *)ItemStack[i].value);
  1840.     }
  1841.  
  1842.     ItemStackDepth = 0;
  1843.     }
  1844. } /* check_stack */
  1845.  
  1846.  
  1847. /******************************************************************************
  1848. *****  ENDE cmd.c
  1849. ******************************************************************************/
  1850.